package powerws

import (
	"fmt"
	"power/core/dao/graphdao"
	"power/core/localwrap"
	"power/core/service/graphs"
	"time"

	"github.com/RocksonZeta/hubx"
	"github.com/go-redis/redis/v7"
)

var log = localwrap.GetLogger().Fork("power/ws/powerws", "PowerNetwork")

type PowerNetwork struct {
	Id  int //gameid
	hub *hubx.Hubx
	// Groups      map[int][]*hubx.Client // groupId : clients
	// Observers   map[int][]*hubx.Client // groupId : clients, group observers
	// Subscribers map[int][]*hubx.Client // groupId : clients, group subscribers
	// graphJson     string
	graphs                  graphs.Graphs
	graphElementProtoClasss graphs.GraphElementProtoClasss
	graphElements           graphs.GraphElements
}

type PowerNetworkOptions struct {
	Id int
	hubx.RedisOptions
	red *redis.Client
}

func NewPowerNetwork(options PowerNetworkOptions) (*PowerNetwork, error) {
	log.Trace().Func("NewPowerNetwork").Send()
	hub, err := hubx.New(hubx.Options{
		TickerPeriod: 1 * time.Second,
		ChannelSize:  options.ChannelSize,
	})
	if err != nil {
		return nil, err
	}
	bc, err := hubx.NewRedisBroadcaster(hub, options.RedisOptions)
	if err != nil {
		return nil, err
	}
	hub.SetBroadcaster(bc)
	r := &PowerNetwork{
		Id:  options.Id,
		hub: hub,
	}
	r.initListeners()
	bc.Start()
	hub.Start()

	return r, nil
}
func (t *PowerNetwork) Hub() *hubx.Hubx {
	return t.hub
}
func (t *PowerNetwork) close() {
	powerNetworks.Delete(t.Id)
	t.hub.CloseAsync()
}

func (t *PowerNetwork) initListeners() {
	log.Trace().Func("initListeners").Send()
	t.hub.AfterJoin = t.afterJoin
	//图
	t.hub.OnWs(graphInit, t.onWsGraphInit)
	t.hub.OnWs(graphLoad, t.onWsGraphLoad)
	t.hub.OnWs(graphUpdate, t.onWsGraphUpdate)
	//元素
	t.hub.OnWs(elementNew, t.onWsElementNew)
	t.hub.OnWs(elementUpdateProps, t.onWsElementUpdateProps)
	t.hub.OnWs(elementUpdateData, t.onWsElementUpdateData)
	t.hub.OnWs(elementDelete, t.onWsElementDelete)
	t.hub.OnWsDefault(t.onWsDefault)
	t.hub.OnDefault(t.onDefault)
	t.hub.Ticker = t.onTick
}

func (t *PowerNetwork) onTick(secs int64) {
	if secs%10 == 0 {
		if t.hub.IsEmpty() {
			t.close()
		}
	}
}
func (t *PowerNetwork) onWsDefault(client *hubx.Client, msg hubx.PartialMessage) {
	log.Trace().Func("onWsDefault").Str("Subject", msg.Subject).Send()
	t.hub.Broadcast(msg.Subject, msg.Data)
}
func (t *PowerNetwork) onDefault(msg hubx.PartialMessage) {
	log.Trace().Func("onDefault").Str("Subject", msg.Subject).Send()
	t.hub.BroadcastWs(msg.Subject, msg.Data)
	// g.hub.SendWs()
}
func (t *PowerNetwork) afterJoin(client *hubx.Client) {
	log.Trace().Func("afterJoin").Send()
	// msg := initMsg{}
	// msg.Id = t.Id
	// msg.GraphJson = t.graphJson

	// t.hub.SendWs("init", msg, client)
	// t.hub.Broadcast("join", getUser(client))
}

func (t *PowerNetwork) onWsPlay(client *hubx.Client, msg hubx.PartialMessage) {
	log.Trace().Func("onWsPlay").Send()
	t.hub.Broadcast("play", nil)
}

//onWsGraphInit 初始化图
func (t *PowerNetwork) onWsGraphInit(client *hubx.Client, msg hubx.PartialMessage) {
	log.Debug().Func("onWsGraphLoad").Str("subject", msg.Subject).Send()
	m := initMsg{}
	m.Id = t.Id
	m.Graph = t.graphs.Get(t.Id)
	fmt.Println("get graph:", m.Graph)
	m.Elements = t.graphElements.ListByGraphId(t.Id)
	m.Protos = t.graphElementProtoClasss.List(m.Graph.Creator)
	t.hub.SendWs(graphInit, m, client)
}

//加载图的json
func (t *PowerNetwork) onWsGraphLoad(client *hubx.Client, msg hubx.PartialMessage) {
	log.Debug().Func("onWsGraphLoad").Str("subject", msg.Subject).Send()
	t.hub.SendWs(graphLoad, t.graphs.Get(t.Id), client)
}

//添加元素
func (t *PowerNetwork) onWsElementNew(client *hubx.Client, msg hubx.PartialMessage) {
	log.Debug().Func("onWsElementNew").Interface("msg", msg).Send()
	var m elementNewMsg
	err := msg.UnmarshalData(&m)
	if err != nil {
		log.Error().Err(err).Msg(err.Error())
		return
	}
	var param graphdao.GraphElementsAddParam
	param.GraphId = t.Id
	param.ProtoId = m.ProtoId
	param.Props = m.Props.Marshal()
	ele := t.graphElements.Add(param)
	newEle := t.graphElements.Get(ele.Id)
	t.hub.Broadcast(msg.Subject, elementNewMsgOut{Element: newEle, Sender: m.Sender, TempId: m.TempId})
}

//删除元素
func (t *PowerNetwork) onWsElementDelete(client *hubx.Client, msg hubx.PartialMessage) {
	log.Debug().Func("onWsElementDelete").Interface("msg", msg).Send()
	var m elementDeleteMsg
	err := msg.UnmarshalData(&m)
	if err != nil {
		log.Error().Err(err).Msg(err.Error())
		return
	}

	t.graphElements.Deletes(m.Ids)
	t.hub.Broadcast(msg.Subject, msg.Data)
}

//更新节点属性
func (t *PowerNetwork) onWsElementUpdateProps(client *hubx.Client, msg hubx.PartialMessage) {
	log.Debug().Func("onWsElementUpdateProps").Interface("msg", msg).Send()
	var m elementUpdateMsg
	err := msg.UnmarshalData(&m)
	if err != nil {
		log.Error().Err(err).Msg(err.Error())
		return
	}
	//todo: 更新需要检查属性
	t.graphElements.UpdateProps(m.Id, m.Props)
	t.hub.Broadcast(msg.Subject, msg.Data)
}

//更新节点数据
func (t *PowerNetwork) onWsElementUpdateData(client *hubx.Client, msg hubx.PartialMessage) {
	log.Debug().Func("onWsElementUpdateData").Interface("msg", msg).Send()
	var m elementUpdateMsg
	err := msg.UnmarshalData(&m)
	if err != nil {
		log.Error().Err(err).Msg(err.Error())
		return
	}
	t.hub.Broadcast(msg.Subject, msg.Data)
}
func (t *PowerNetwork) onWsGraphUpdate(client *hubx.Client, msg hubx.PartialMessage) {
	log.Trace().Func("onWsGraphUpdate").Interface("msg", msg).Send()
	var m graphUpdateMsg
	err := msg.UnmarshalData(&m)
	if err != nil {
		log.Error().Err(err).Msg(err.Error())
		return
	}
	t.graphs.Update(graphs.GraphsUpdateParam{Id: t.Id, Name: m.Name, Props: m.Props})
	t.hub.BroadcastWs(msg.Subject, msg.Data)
}
